<?php
/**
 * Created by PhpStorm
 * User: 龍zero
 * Date: 2022-04-10
 * Time: 16:28
 */
declare(strict_types=1);
namespace App\Service;


use App\Exception\ForbiddenException;
use App\Exception\NotFoundException;
use App\Lib\Enum\GroupLevel;
use App\Model\LinGroup;
use App\Model\LinGroupPermission;
use App\Model\LinUserGroup;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

class GroupService
{
    /**
     * @Inject()
     * @var PermissionService
     */
    private $permissionService;

    public function getUserGroupsByUserID($userId)
    {
        $groups = LinUserGroup::where('user_id',$userId)->with(['groups'=>function($query){
            $query->select(['id','name','info']);
        }])->get()->toArray();
        return array_column($groups,'groups');

    }

    public function getUserGroupIdsByUserId($userId)
    {
        $groups = $this->getUserGroupsByUserID($userId);
        return array_column($groups,'id');
    }

    public function checkIsRootByUserId($userId){
        $group = LinGroup::where('level',GroupLevel::ROOT)->first();
        $relation = LinUserGroup::where('user_id',$userId)->where('group_id',$group->id)->get();
        if($relation->isEmpty()){
            return false;
        }
        return true;
    }

    public function getParticularGroupByLevel($groupLevel){
        if($groupLevel === GroupLevel::USER){
            return null;
        }else{
            $group = LinGroup::where('level',$groupLevel)->first();
        }
        return  $group;
    }

    public function getParticularGroupIdByLevel($groupLevel){
        $group = $this->getParticularGroupByLevel($groupLevel);
        return $group == null ? 0 : $group->id;
    }

    public function getParticularList($rootGroupId){
        return LinGroup::where('id','<>',$rootGroupId)->get(['id','name','info'])->toArray();
    }

    public function getGroupAndPermissions($id){
        $group = LinGroup::find($id)->makeHidden(['level'])->toArray();
        if(!$group){
            throw new NotFoundException(10024);
        }
        $group['permissions'] = $this->permissionService->getPermissionByGroupId($id);
        return $group;
    }

    public function updateGroup($id,$params){
        $group = LinGroup::find($id);
        if(!$group){
            throw new NotFoundException(10024);
        }
        $this->checkGroupExistByName($params['name']);
        $group->name = $params['name'];
        $group->info = $params['info'];
        $group->save();
    }

    public function addUserGroupRelations($userId,$addIds){
        $insert = [];
        foreach ($addIds as $groupId){
            $insert[] = ['user_id' => $userId,'group_id'=>$groupId];
        }
        LinUserGroup::insert($insert);
    }

    public function deleteUserGroupRelations($userId,$removeIds){
        LinUserGroup::query()->where('user_id',$userId)
            ->whereIn('group_id',$removeIds)
            ->delete();
    }

    public function deleteGroup($id){
        #超管与guest组不支持删除
        #用户组下无用户可删除
        $rootGroupId = $this->getParticularGroupIdByLevel(GroupLevel::ROOT);
        $guestGroupId = $this->getParticularGroupIdByLevel(GroupLevel::GUEST);
        if($id == $rootGroupId){
            throw new ForbiddenException(10074);
        }
        if($id == $guestGroupId){
            throw new ForbiddenException(10075);
        }
        $group = LinGroup::find($id);
        if(!$group){
            throw new NotFoundException(10024);
        }
        $count = LinUserGroup::where('group_id',$id)->count();
        if($count > 0 ){
            throw new ForbiddenException(10027);
        }
        #刪除分组以及分组权限
        Db::beginTransaction();
        try {
            LinGroupPermission::query()->where('group_id',$id)->delete();
            LinGroup::query()->where('id',$id)->delete();
            Db::commit();
        }catch (\Exception $e){
            Db::rollBack();
            throw $e;
        }
    }

    private function checkGroupExistByName($name){
        $exist = LinGroup::where('name',$name)->first();
        if($exist){
            throw new ForbiddenException(10072);
        }
    }
}